package com.tanhua.dubbo.api;

import cn.hutool.core.collection.CollectionUtil;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@DubboService
public class RecommendUserApiImpl implements RecommendUserApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 推荐给登录用户的今日佳人
     *
     * @param loginUserId
     * @return
     */
    @Override
    public RecommendUser todayBest(Long loginUserId) {
        // 构建条件
        Query query = new Query(Criteria.where("toUserId").is(loginUserId));
        // 缘分降序
        query.with(Sort.by(Sort.Order.desc("score")));
        // 查询取第一条
        RecommendUser todayBest = mongoTemplate.findOne(query, RecommendUser.class);
        return todayBest;
    }

    /**
     * 通过登录用户id分页查询推荐的佳人列表
     *
     * @param userId
     * @return
     */
    @Override
    public PageResult findPageByUserId(Long userId,Long page, Long pageSize) {
        List<RecommendUser> list = new ArrayList<>();
        //1. 构建查询条件
        Query query = new Query(Criteria.where("toUserId").is(userId));
        //2. 查询符合条件的总数
        long total = mongoTemplate.count(query, RecommendUser.class);
        //3. 计算开始行号
        long start = (page-1) * pageSize;
        //4. 总数>开始行号
        if(total > start) {
            //5. 设置分页参数
            query.skip(start).limit(pageSize.intValue());
            //6. 分页查询
            list = mongoTemplate.find(query, RecommendUser.class);
        }
        //7. 构建pageResult再返回
        return new PageResult(page, pageSize, total, list);
    }

    /**
     * 查询登录用户与佳人缘分值
     *
     * @param loginUserId
     * @param userId
     * @return
     */
    @Override
    public RecommendUser findByUserId(Long loginUserId, Long userId) {
        Query query = new Query(Criteria.where("toUserId").is(loginUserId).and("userId").is(userId));
        return mongoTemplate.findOne(query, RecommendUser.class);
    }

    /**
     * 探花功能中用户列表
     * 随机查询10个推荐用户，排除userLike表中的记录
     *
     *
     * @param loginUserId
     * @param num
     * @return
     */
    @Override
    public List<RecommendUser> findCards(Long loginUserId, int num) {
        //1. 构建查询的条件1：toUserId=loginUserId
        Criteria toUserId = Criteria.where("toUserId").is(loginUserId);

        //3. 抽样查询, p2:条件,具体统计方式
        List<AggregationOperation> list = new ArrayList<>();
        // 匹配条件, toUserId=登录用户id
        list.add(Aggregation.match(toUserId));

        //2. 条件2： 排除userLike表中的记录， 构建userLike查询条件
        Query userLikeQuery = new Query(Criteria.where("userId").is(loginUserId));
        List<UserLike> userLikeList = mongoTemplate.find(userLikeQuery, UserLike.class);
        if(CollectionUtil.isNotEmpty(userLikeList)){
            List<Long> userLikeIds = userLikeList.stream().map(UserLike::getLikeUserId).collect(Collectors.toList());
            // 构建查询recommendUser表时的排除
            Criteria notInUserLikeIds = Criteria.where("userId").nin(userLikeIds);
            // 抽样时要排除已经操作过的佳人id
            list.add(Aggregation.match(notInUserLikeIds));
        }

        // 取样品，随机抽10个
        list.add(Aggregation.sample(num));
        // 统计方式, p1: 输入类型与泛型要一致, p2:条件,具体统计方式
        //        p1:Class<T> type, p2: List<? extends AggregationOperation> operations
        TypedAggregation<RecommendUser> recommendUserTypedAggregation = TypedAggregation.newAggregation(RecommendUser.class, list);
        //p1: 统计方式， p2: 返回结果的类型
        AggregationResults<RecommendUser> results = mongoTemplate.aggregate(recommendUserTypedAggregation, RecommendUser.class);
        // 统计抽样结果
        return results.getMappedResults();
    }
}
